package com.rpay.common.util.http.request;

import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.HttpClient;
import org.apache.http.protocol.HttpContext;

/**
 * @author： Wangwei
 * @date： 2017/9/20
 * @desc：HTTP请求配置
 */
public class HttpConfig {
	
	private HttpConfig(){};
	
	/**
	 * 获取实例
	 * @return
	 */
	public static HttpConfig custom(){
		return new HttpConfig();
	}

	/**
	 * HttpClient对象
	 */
	private HttpClient client;

	/**
	 * Header头信息
	 */
	private Header[] headers;
	
	/**
	 * 请求方法(默认为GET)
	 */
	private HttpMethod method= HttpMethod.GET;
	
	/**
	 * 用于cookie操作
	 */
	private HttpContext context;

	/**
	 * get传递参数
	 */
	private Map<String, String> getMap;

	/**
	 * form传递参数
	 */
	private Map<String, Object> formMap;

	/**
	 * rest参数
	 */
	private Map<String,String> restMap;

	/**
	 * 以body格式作为输入参数
	 */
	private String body;

	/**
	 * 输入输出编码
	 */
	private String encoding=Charset.defaultCharset().displayName();

	/**
	 * 输入编码
	 */
	private String inEncode;

	/**
	 * 输出编码
	 */
	private String outEncode;

	/**
	 * 解决多线程下载时，stream被close的问题(ThreadLocal会出现单线程多调用的问题)
	 */
	private OutputStream out;
	
	/**
	 * 解决多线程处理时，url被覆盖问题(ThreadLocal会出现单线程多调用的问题)
	 */
	private String url;

	private HttpEntity httpEntity;
	
	/**
	 * HttpClient对象
	 */
	public HttpConfig client(HttpClient client) {
		this.client = client;
		return this;
	}
	
	/**
	 * 资源url
	 */
	public HttpConfig url(String url) {
		this.url = url;
		return this;
	}
	
	/**
	 * Header头信息(是否返回response中的headers)
	 */
	public HttpConfig header(Header[] headers) {
		this.headers = headers;
		return this;
	}
	
	/**
	 * 请求方法
	 */
	public HttpConfig method(HttpMethod method) {
		this.method = method;
		return this;
	}
	
	/**
	 * cookie操作相关
	 */
	public HttpConfig context(HttpContext context) {
		this.context = context;
		return this;
	}

	/**
	 * json传递参数
	 */
	public HttpConfig body(String body) {
		this.body = body;
		return this;
	}

	public HttpConfig httpEntity(HttpEntity httpEntity) {
		this.httpEntity = httpEntity;
		return this;
	}

	/**
	 * get传递参数
	 */
	public HttpConfig param(Map<String, String> map) {
		synchronized (getClass()) {
			if (map != null) {
				if(this.getMap==null){
					this.getMap = new ConcurrentHashMap<>(16);
				}
				this.getMap.putAll(map);
			}
		}
		return this;
	}

	/**
	 * get传递参数
	 */
	public HttpConfig param(String key,String value) {
		synchronized (getClass()) {
			if(this.getMap==null){
				this.getMap = new ConcurrentHashMap<>(16);
			}
			if (value!=null && !value.isEmpty()) {
				this.getMap.put(key,value);
			}
		}
		return this;
	}

	/**
	 * form传递参数
	 */
	public HttpConfig formParam(Map<String, Object> map) {
		synchronized (getClass()) {
			if (map != null) {
				if(this.formMap==null){
					this.formMap = new ConcurrentHashMap<>(16);
				}
				this.formMap.putAll(map);
			}
		}
		return this;
	}

	/**
	 *  form传递参数
	 */
	public HttpConfig formParam(String key,Object value) {
		synchronized (getClass()) {
			if(this.formMap==null){
				this.formMap = new ConcurrentHashMap<>(16);
			}
			this.formMap.put(key,value);
		}
		return this;
	}

	/**
	 * rest风格请求参数传递
	 * @param map
	 * @return
	 */
	public HttpConfig rest(Map<String, String> map) {
		synchronized (getClass()) {
			if (map != null) {
				if(this.restMap==null){
					this.restMap = new ConcurrentHashMap<>(16);
				}
				this.restMap.putAll(map);
			}
		}
		return this;
	}

	/**
	 * rest风格请求参数传递
	 * @param key 键
	 * @param value 值
	 * @return HttpConfig
	 */
	public HttpConfig rest(String key,String value) {
		synchronized (getClass()) {
			if(this.restMap==null){
				this.restMap = new ConcurrentHashMap<>(16);
			}
			this.restMap.put(key,value);
		}
		return this;
	}

	/**
	 * 输入输出编码
	 */
	public HttpConfig encoding(String encoding) {
		//设置输入输出
		inEncode(encoding);
		outEncode(encoding);
		this.encoding = encoding;
		return this;
	}
	
	/**
	 * 输入编码
	 */
	public HttpConfig inEncode(String encoding) {
		this.inEncode = encoding;
		return this;
	}
	
	/**
	 * 输出编码
	 */
	public HttpConfig outEncode(String encoding) {
		this.inEncode = encoding;
		return this;
	}
	
	/**
	 * 输出流对象
	 */
	public HttpConfig out(OutputStream out) {
		this.out = out;
		return this;
	}

	public HttpClient client() {
		return client;
	}
	
	public Header[] headers() {
		return headers;
	}

	public String url() {
		return url;
	}

	public HttpMethod method() {
		return method;
	}

	public HttpContext context() {
		return context;
	}

	public Map<String, String> getMap() {
		return getMap;
	}

	public Map<String, Object> formMap() {
		return formMap;
	}


	public Map<String, String> rest() {
		return restMap;
	}

	public String body() {
		return body;
	}

	public String encoding() {
		return encoding;
	}

	public String inEncode() {
		return inEncode == null ? encoding : inEncode;
	}

	public String outEncode() {
		return outEncode == null ? encoding : outEncode;
	}

	public OutputStream out() {
		return out;
	}
}